package controller

import (
	"context"
	"fmt"
	"log"
	"sync"

	"github.com/louloulin/dataflare/pkg/controller/client"
	"github.com/louloulin/dataflare/pkg/controller/membership"
	"github.com/louloulin/dataflare/pkg/controller/metadata"
	"github.com/louloulin/dataflare/pkg/controller/resource"
)

// ControllerConfig 表示控制器配置
type ControllerConfig struct {
	// ClusterConfig 是集群配置
	ClusterConfig *membership.ClusterConfig
	// MetadataStore 是元数据存储
	MetadataStore metadata.MetadataStore
}

// DefaultControllerConfig 返回默认控制器配置
func DefaultControllerConfig() *ControllerConfig {
	return &ControllerConfig{
		ClusterConfig: membership.DefaultClusterConfig(),
		MetadataStore: metadata.NewInMemoryMetadataStore(),
	}
}

// Controller 表示控制器
type Controller struct {
	// config 是控制器配置
	config *ControllerConfig
	// clusterManager 是集群管理器
	clusterManager *membership.ClusterManager
	// metadataManager 是元数据管理器
	metadataManager *metadata.MetadataManager
	// resourceManager 是资源管理器
	resourceManager *resource.ResourceAllocationManager
	// clientCoordinator 是客户端协调器
	clientCoordinator *client.ClientCoordinator
	// clientRouter 是客户端请求路由器
	clientRouter *client.ClientRequestRouter
	// ctx 是上下文
	ctx context.Context
	// cancel 是取消函数
	cancel context.CancelFunc
	// wg 是等待组
	wg sync.WaitGroup
}

// NewController 创建一个新的控制器
func NewController(config *ControllerConfig) (*Controller, error) {
	if config == nil {
		config = DefaultControllerConfig()
	}

	// 创建上下文
	ctx, cancel := context.WithCancel(context.Background())

	// 创建集群管理器
	clusterManager, err := membership.NewClusterManager(config.ClusterConfig)
	if err != nil {
		cancel()
		return nil, fmt.Errorf("failed to create cluster manager: %w", err)
	}

	// 创建元数据管理器
	metadataManager := metadata.NewMetadataManager(config.MetadataStore)

	// 创建资源管理器
	resourceManager := resource.NewResourceAllocationManager(clusterManager)

	// 创建客户端协调器
	clientCoordinator := client.NewClientCoordinator(metadataManager)

	// 创建客户端请求路由器
	clientRouter := client.NewClientRequestRouter()

	return &Controller{
		config:            config,
		clusterManager:    clusterManager,
		metadataManager:   metadataManager,
		resourceManager:   resourceManager,
		clientCoordinator: clientCoordinator,
		clientRouter:      clientRouter,
		ctx:               ctx,
		cancel:            cancel,
	}, nil
}

// Start 启动控制器
func (c *Controller) Start() error {
	log.Println("Starting controller")

	// 启动集群管理器
	err := c.clusterManager.Start()
	if err != nil {
		return fmt.Errorf("failed to start cluster manager: %w", err)
	}

	// 注册请求处理器
	c.registerRequestHandlers()

	return nil
}

// Stop 停止控制器
func (c *Controller) Stop() error {
	log.Println("Stopping controller")

	// 取消上下文
	c.cancel()

	// 停止集群管理器
	err := c.clusterManager.Stop()
	if err != nil {
		return fmt.Errorf("failed to stop cluster manager: %w", err)
	}

	// 等待所有goroutine退出
	c.wg.Wait()

	return nil
}

// Join 加入集群
func (c *Controller) Join(addresses []string) (int, error) {
	return c.clusterManager.Join(addresses)
}

// Leave 离开集群
func (c *Controller) Leave() error {
	return c.clusterManager.Leave()
}

// GetClusterManager 获取集群管理器
func (c *Controller) GetClusterManager() *membership.ClusterManager {
	return c.clusterManager
}

// GetMetadataManager 获取元数据管理器
func (c *Controller) GetMetadataManager() *metadata.MetadataManager {
	return c.metadataManager
}

// GetResourceManager 获取资源管理器
func (c *Controller) GetResourceManager() *resource.ResourceAllocationManager {
	return c.resourceManager
}

// GetClientCoordinator 获取客户端协调器
func (c *Controller) GetClientCoordinator() *client.ClientCoordinator {
	return c.clientCoordinator
}

// GetClientRouter 获取客户端请求路由器
func (c *Controller) GetClientRouter() *client.ClientRequestRouter {
	return c.clientRouter
}

// registerRequestHandlers 注册请求处理器
func (c *Controller) registerRequestHandlers() {
	// 注册元数据请求处理器
	c.clientRouter.RegisterHandler("metadata.get", &MetadataGetHandler{manager: c.metadataManager})
	c.clientRouter.RegisterHandler("metadata.list", &MetadataListHandler{manager: c.metadataManager})
	c.clientRouter.RegisterHandler("metadata.create", &MetadataCreateHandler{manager: c.metadataManager})
	c.clientRouter.RegisterHandler("metadata.update", &MetadataUpdateHandler{manager: c.metadataManager})
	c.clientRouter.RegisterHandler("metadata.delete", &MetadataDeleteHandler{manager: c.metadataManager})

	// 注册集群请求处理器
	c.clientRouter.RegisterHandler("cluster.members", &ClusterMembersHandler{manager: c.clusterManager})
	c.clientRouter.RegisterHandler("cluster.join", &ClusterJoinHandler{controller: c})
	c.clientRouter.RegisterHandler("cluster.leave", &ClusterLeaveHandler{controller: c})

	// 注册资源请求处理器
	c.clientRouter.RegisterHandler("resource.allocate", &ResourceAllocateHandler{manager: c.resourceManager})
	c.clientRouter.RegisterHandler("resource.release", &ResourceReleaseHandler{manager: c.resourceManager})
	c.clientRouter.RegisterHandler("resource.status", &ResourceStatusHandler{manager: c.resourceManager})
}

// MetadataGetHandler 表示元数据获取处理器
type MetadataGetHandler struct {
	manager *metadata.MetadataManager
}

// HandleRequest 处理请求
func (h *MetadataGetHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	typeStr, ok := request.Data["type"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid type parameter",
			Timestamp: request.Timestamp,
		}
	}

	id, ok := request.Data["id"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid id parameter",
			Timestamp: request.Timestamp,
		}
	}

	// 获取元数据
	meta, exists := h.manager.Get(metadata.MetadataType(typeStr), id)
	if !exists {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("metadata %s of type %s not found", id, typeStr),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"metadata": meta,
		},
		Timestamp: request.Timestamp,
	}
}

// MetadataListHandler 表示元数据列表处理器
type MetadataListHandler struct {
	manager *metadata.MetadataManager
}

// HandleRequest 处理请求
func (h *MetadataListHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	typeStr, ok := request.Data["type"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid type parameter",
			Timestamp: request.Timestamp,
		}
	}

	// 获取元数据列表
	metaList, err := h.manager.List(metadata.MetadataType(typeStr))
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to list metadata: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"metadata": metaList,
		},
		Timestamp: request.Timestamp,
	}
}

// MetadataCreateHandler 表示元数据创建处理器
type MetadataCreateHandler struct {
	manager *metadata.MetadataManager
}

// HandleRequest 处理请求
func (h *MetadataCreateHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	typeStr, ok := request.Data["type"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid type parameter",
			Timestamp: request.Timestamp,
		}
	}

	id, ok := request.Data["id"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid id parameter",
			Timestamp: request.Timestamp,
		}
	}

	data, ok := request.Data["data"].(map[string]interface{})
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid data parameter",
			Timestamp: request.Timestamp,
		}
	}

	// 创建元数据
	meta, err := h.manager.Create(metadata.MetadataType(typeStr), id, data)
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to create metadata: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"metadata": meta,
		},
		Timestamp: request.Timestamp,
	}
}

// MetadataUpdateHandler 表示元数据更新处理器
type MetadataUpdateHandler struct {
	manager *metadata.MetadataManager
}

// HandleRequest 处理请求
func (h *MetadataUpdateHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	typeStr, ok := request.Data["type"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid type parameter",
			Timestamp: request.Timestamp,
		}
	}

	id, ok := request.Data["id"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid id parameter",
			Timestamp: request.Timestamp,
		}
	}

	data, ok := request.Data["data"].(map[string]interface{})
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid data parameter",
			Timestamp: request.Timestamp,
		}
	}

	// 更新元数据
	meta, err := h.manager.Update(metadata.MetadataType(typeStr), id, data)
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to update metadata: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"metadata": meta,
		},
		Timestamp: request.Timestamp,
	}
}

// MetadataDeleteHandler 表示元数据删除处理器
type MetadataDeleteHandler struct {
	manager *metadata.MetadataManager
}

// HandleRequest 处理请求
func (h *MetadataDeleteHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	typeStr, ok := request.Data["type"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid type parameter",
			Timestamp: request.Timestamp,
		}
	}

	id, ok := request.Data["id"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid id parameter",
			Timestamp: request.Timestamp,
		}
	}

	// 删除元数据
	err := h.manager.Delete(metadata.MetadataType(typeStr), id)
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to delete metadata: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Timestamp: request.Timestamp,
	}
}

// ClusterMembersHandler 表示集群成员处理器
type ClusterMembersHandler struct {
	manager *membership.ClusterManager
}

// HandleRequest 处理请求
func (h *ClusterMembersHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取成员列表
	members := h.manager.Members()

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"members": members,
		},
		Timestamp: request.Timestamp,
	}
}

// ClusterJoinHandler 表示集群加入处理器
type ClusterJoinHandler struct {
	controller *Controller
}

// HandleRequest 处理请求
func (h *ClusterJoinHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	addressesIface, ok := request.Data["addresses"]
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing addresses parameter",
			Timestamp: request.Timestamp,
		}
	}

	addressesArr, ok := addressesIface.([]interface{})
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "invalid addresses parameter, expected array",
			Timestamp: request.Timestamp,
		}
	}

	addresses := make([]string, len(addressesArr))
	for i, addr := range addressesArr {
		addrStr, ok := addr.(string)
		if !ok {
			return &client.ClientResponse{
				ClientID:  request.ClientID,
				RequestID: request.RequestID,
				Success:   false,
				Error:     "invalid address in addresses array, expected string",
				Timestamp: request.Timestamp,
			}
		}
		addresses[i] = addrStr
	}

	// 加入集群
	n, err := h.controller.Join(addresses)
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to join cluster: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"joined": n,
		},
		Timestamp: request.Timestamp,
	}
}

// ClusterLeaveHandler 表示集群离开处理器
type ClusterLeaveHandler struct {
	controller *Controller
}

// HandleRequest 处理请求
func (h *ClusterLeaveHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 离开集群
	err := h.controller.Leave()
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to leave cluster: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Timestamp: request.Timestamp,
	}
}

// ResourceAllocateHandler 表示资源分配处理器
type ResourceAllocateHandler struct {
	manager *resource.ResourceAllocationManager
}

// HandleRequest 处理请求
func (h *ResourceAllocateHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	requirementsIface, ok := request.Data["requirements"]
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing requirements parameter",
			Timestamp: request.Timestamp,
		}
	}

	requirementsArr, ok := requirementsIface.([]interface{})
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "invalid requirements parameter, expected array",
			Timestamp: request.Timestamp,
		}
	}

	requirements := make([]resource.ResourceRequirement, len(requirementsArr))
	for i, req := range requirementsArr {
		reqMap, ok := req.(map[string]interface{})
		if !ok {
			return &client.ClientResponse{
				ClientID:  request.ClientID,
				RequestID: request.RequestID,
				Success:   false,
				Error:     "invalid requirement in requirements array, expected object",
				Timestamp: request.Timestamp,
			}
		}

		typeStr, ok := reqMap["type"].(string)
		if !ok {
			return &client.ClientResponse{
				ClientID:  request.ClientID,
				RequestID: request.RequestID,
				Success:   false,
				Error:     "missing or invalid type in requirement",
				Timestamp: request.Timestamp,
			}
		}

		quantity, ok := reqMap["quantity"].(float64)
		if !ok {
			return &client.ClientResponse{
				ClientID:  request.ClientID,
				RequestID: request.RequestID,
				Success:   false,
				Error:     "missing or invalid quantity in requirement",
				Timestamp: request.Timestamp,
			}
		}

		requirements[i] = resource.ResourceRequirement{
			Type:     resource.ResourceType(typeStr),
			Quantity: resource.ResourceQuantity(quantity),
		}
	}

	// 分配资源
	nodeID, err := h.manager.AllocateTask(requirements)
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to allocate resources: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"node_id": nodeID,
		},
		Timestamp: request.Timestamp,
	}
}

// ResourceReleaseHandler 表示资源释放处理器
type ResourceReleaseHandler struct {
	manager *resource.ResourceAllocationManager
}

// HandleRequest 处理请求
func (h *ResourceReleaseHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取请求参数
	nodeID, ok := request.Data["node_id"].(string)
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing or invalid node_id parameter",
			Timestamp: request.Timestamp,
		}
	}

	requirementsIface, ok := request.Data["requirements"]
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "missing requirements parameter",
			Timestamp: request.Timestamp,
		}
	}

	requirementsArr, ok := requirementsIface.([]interface{})
	if !ok {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     "invalid requirements parameter, expected array",
			Timestamp: request.Timestamp,
		}
	}

	requirements := make([]resource.ResourceRequirement, len(requirementsArr))
	for i, req := range requirementsArr {
		reqMap, ok := req.(map[string]interface{})
		if !ok {
			return &client.ClientResponse{
				ClientID:  request.ClientID,
				RequestID: request.RequestID,
				Success:   false,
				Error:     "invalid requirement in requirements array, expected object",
				Timestamp: request.Timestamp,
			}
		}

		typeStr, ok := reqMap["type"].(string)
		if !ok {
			return &client.ClientResponse{
				ClientID:  request.ClientID,
				RequestID: request.RequestID,
				Success:   false,
				Error:     "missing or invalid type in requirement",
				Timestamp: request.Timestamp,
			}
		}

		quantity, ok := reqMap["quantity"].(float64)
		if !ok {
			return &client.ClientResponse{
				ClientID:  request.ClientID,
				RequestID: request.RequestID,
				Success:   false,
				Error:     "missing or invalid quantity in requirement",
				Timestamp: request.Timestamp,
			}
		}

		requirements[i] = resource.ResourceRequirement{
			Type:     resource.ResourceType(typeStr),
			Quantity: resource.ResourceQuantity(quantity),
		}
	}

	// 释放资源
	err := h.manager.ReleaseTask(nodeID, requirements)
	if err != nil {
		return &client.ClientResponse{
			ClientID:  request.ClientID,
			RequestID: request.RequestID,
			Success:   false,
			Error:     fmt.Sprintf("failed to release resources: %v", err),
			Timestamp: request.Timestamp,
		}
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Timestamp: request.Timestamp,
	}
}

// ResourceStatusHandler 表示资源状态处理器
type ResourceStatusHandler struct {
	manager *resource.ResourceAllocationManager
}

// HandleRequest 处理请求
func (h *ResourceStatusHandler) HandleRequest(request *client.ClientRequest) *client.ClientResponse {
	// 获取所有节点资源
	nodeResources := h.manager.GetAllNodeResources()

	// 构建响应数据
	data := make(map[string]interface{})
	for nodeID, resources := range nodeResources {
		nodeData := make(map[string]interface{})
		for resourceType, capacity := range resources.GetAllCapacities() {
			nodeData[string(resourceType)] = map[string]interface{}{
				"total":      capacity.Total,
				"used":       capacity.Used,
				"available":  capacity.Available(),
				"utilization": capacity.UtilizationRatio(),
			}
		}
		data[nodeID] = nodeData
	}

	// 返回响应
	return &client.ClientResponse{
		ClientID:  request.ClientID,
		RequestID: request.RequestID,
		Success:   true,
		Data: map[string]interface{}{
			"resources": data,
		},
		Timestamp: request.Timestamp,
	}
}
